//Setvalues to vertex...
//
#include"mPointArray.h"
//********************************************************************//
//**                       mPointArray                             **//
//********************************************************************//
//SWAP mPoint position
bool mPointArray::Swap(int a,int b)
{
    std::swap(at(a),at(b));
    return true;
};
//Try to Calculate shortest path and give lenght
void mPointArray::GetShortestPath()
{
    mPointArray CA;
    CA.Add(*this);

    int best=0;
    double bestL=1000000000;

    for(uint a=0; a<size(); a++)
    {
        CA.Add(*this);
        CA.Swap(0,a);
        double dis=0,disT=0,disA=0;

        for(uint b=1; b<CA.size(); b++)
        {
            disT=10000000;
            int Row=b;
            for(uint c=b; c<CA.size(); c++)
            {
                dis = CA.at(b-1).GetDistanceXY(CA.at(c));
                if(dis<disT)
                {
                    disT=dis;
                    Row=c;
                };
            }
            CA.Swap(b,Row);
            disA += dis;
        }
        if(disA<bestL)
        {
            bestL=disA;
            best=a;
        };
        CA.Clear();
    }

    Swap(best,0);

    double dis=0,disT;
    uint Row,c;

    for(uint b=0; b<(size()-1); b++)
    {
        disT=10000000;
        Row=b+1;
        for(c=Row; c<size(); c++)
        {
            dis = at(b).GetDistanceXY(at(c));
            if(dis<disT)
            {
                disT=dis;
                Swap(Row,c);
            };
        }
    }
};
//SORT X
void mPointArray::LevelZ(double z)
{
    for(uint a=0; a<size(); a++)
    {
        at(a).z=z;
    }
};

//SORT X
void mPointArray::SortX()
{
    uint l=0;
    bool hit;
    if(size()==0)return;
    for(uint a=0; a<(size()-1); a++)
    {
        double lx=10000000000;
        hit = false;
        for(uint b=a; b<size(); b++)
        {
            if(at(b).x < lx)
            {
                hit = true;
                lx=at(b).x;
                l=b;
            };
        }
        if(hit)Swap(a,l);
    }
};

//SORT X
void mPointArray::SortY()
{
    uint l=0;
    bool hit;
    if(size()==0)return;
    for(uint a=0; a<(size()-1); a++)
    {
        double ly=10000000000;
        hit = false;
        for(uint b=a; b<size(); b++)
        {
            if(at(b).y < ly)
            {
                hit = true;
                ly=at(b).y;
                l=b;
            };
        }
        if(hit)Swap(a,l);
    }
};


bool mPointArray::Del(uint a)
{
     erase (begin()+a);
     return true;
};

//Clear array
void mPointArray::Clear()
{
    ClearArea();
    clear();
};

//
int mPointArray::Add(mPoint P1,bool removedouble)
{
    test(P1);
    if(removedouble==true)
    {
        for(uint a=0; a<size(); a++)
        {
            if(at(a).Match(P1))return a;
        }
    }
    push_back(P1);

    return size()-1;
};
//
int mPointArray::Add(mPointArray V,bool removedouble)
{
    uint s=0;
    for(uint a=0;a<V.size();a++)
        s = Add(V.at(a),removedouble);

    return s;
};

void mPointArray::Scale(double s)
{
    for(uint a=0;a<size();a++)
    {
        at(a) *= s;
    }
};

mPoint mPointArray::Bezier(double paikka)
{
    mPointArray A1,A2;
    if(size()<3) return mP(0,0);

    for(uint a=0;a<(size()-1);a++)
    {
        A1.Add(at(a).GetMidPoint(at(a+1),paikka));
    }

    if(A1.size()==1) return A1.at(0);

    while(true)
    {
        for(uint a=0;a<(A1.size()-1);a++)
        {
            A2.Add(A1.at(a).GetMidPoint(A1.at(a+1),paikka) );
        }
        if(A2.size()==1) return A2.at(0);
        A1.Clear();

        //*****************************//
        for(uint a=0;a<(A2.size()-1);a++)
        {
            A1.Add(A2.at(a).GetMidPoint(A2.at(a+1),paikka) );
        }
        if(A1.size()==1) return A1.at(0);
        A2.Clear();
    }


    return mP(NAN,NAN);

};

//**************************************************************************************************//
//**                                 Functions using mPoint/mPointArray                         **//
//**************************************************************************************************//

//Translate
bool mPointArray::Translate(mPoint P2)
{
    for(uint a=0; a<size(); a++)
    {
        at(a) = at(a)+P2;
    }
    return true;
}
//Rotate list from X axis
bool mPointArray::RotateX(double ANGLE)
{
    for(uint a=0; a<size(); a++)
    {
        //ROTATE Z
        double z = (at(a).z*cos(ANGLE))-(at(a).y*sin(ANGLE));
        double y = (at(a).z*sin(ANGLE))+(at(a).y*cos(ANGLE));
        at(a).SetValue(at(a).x,y,z);
    };

    return true;
}

//Rotate list from Z axis
bool mPointArray::RotateZ(double ANGLE)
{
    for(uint a=0; a<size(); a++)
    {
        //ROTATE Z
        double x = (at(a).x*cos(ANGLE))-(at(a).y*sin(ANGLE));
        double y = (at(a).x*sin(ANGLE))+(at(a).y*cos(ANGLE));
        at(a).SetValue(x,y,at(a).z);
    };

    return true;
}
//Projection
bool mPointArray::Projection(double Dist)
{
    for(uint a=0; a<size(); a++)
    {
        double k = (Dist+at(a).z)/Dist;
        double x =  at(a).x / k;
        double y =  at(a).y / k;
        at(a).SetValue(x,-y,-at(a).z);
    };

    return true;
}

//************************************//
// two points find lines
//************************************//
uint mPointArray::Select(double X,double Y,double DIST)
{
     //LINE
    /*for(uint a=0;a<Size();a=a+2)
    {
        double A = X - at(a).x;
        double B = Y - at(a).y;
        double C = at(a+1).x - at(a).x;
        double D = at(a+1).y - at(a).y;

        double dot = A * C + B * D;
        double len_sq = C * C + D * D;
        double param = dot / len_sq;

        double xi,yi;

        if (param < 0)
        {
            xi=at(a).x;
            yi=at(a).y;
        }
        else if (param > 1)
        {
            xi=at(a+1).x;
            yi=at(a).y;
        }
        else
        {
            xi = at(a).x + param * C;
            yi = at(a).y + param * D;
        }
        if(  Distance2D(X,Y,xi,yi) < DIST) return at(a).msg;
    }*/
    return -1;
}
